package us.mmapp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import us.mmapp.entities.CommentEntity;
import us.mmapp.entities.FriendEntity;
import us.mmapp.entities.ObjectEntity;
import us.mmapp.util.ApplicationData;
import us.mmapp.util.ObjectEntityPredicate;

public class SearchManager {
	
	private ArrayList<ObjectEntity> mObjects;
	
	public enum PredicateType
	{
		Title,
		Description,
		Tags,
		Comment,
		Friend,
		Any
	}
	
	public SearchManager(ArrayList<ObjectEntity> objects)
	{
		mObjects = objects;
	}
	
	public ArrayList<ObjectEntity> search(PredicateType type, String keyword, boolean ignoreCase, boolean contain)
	{
		//If ignore case first convert the keyword to lower case
		if (ignoreCase)
			keyword = keyword.toLowerCase();
		ArrayList<ObjectEntity> result = new ArrayList<ObjectEntity>();
		if (type == PredicateType.Any)
		{
			ObjectEntityPredicate[] predicates = new ObjectEntityPredicate[5];
			predicates[0] = selectPredicate(PredicateType.Title, ignoreCase);
			predicates[1] = selectPredicate(PredicateType.Description, ignoreCase);
			predicates[2] = selectPredicate(PredicateType.Comment, ignoreCase);
			predicates[3] = selectPredicate(PredicateType.Tags, ignoreCase);
			predicates[4] = selectPredicate(PredicateType.Friend, ignoreCase);
			for (int i = 0; i < mObjects.size(); i++)
			{
				for (int j = 0; j < predicates.length; j++)
				{
					if (predicates[j].eval(mObjects.get(i), keyword) == contain)
					{
						result.add(mObjects.get(i));
					}
				}
			}
		}
		else
		{
			ObjectEntityPredicate predicate = selectPredicate(type, ignoreCase);
			for (int i = 0; i < mObjects.size(); i++)
			{
				if (predicate.eval(mObjects.get(i), keyword) == contain)
				{
					result.add(mObjects.get(i));
				}
			}
		}
		return result;
	}
	
	private ObjectEntityPredicate selectPredicate(PredicateType type, boolean ignoreCase)
	{
		if (!ignoreCase)
		{
			if (type == PredicateType.Title)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					return entity.getTitle().contains(value);
				}
			};
			else if (type == PredicateType.Description)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					return entity.getDescription().contains(value);
				}
			};
			else if (type == PredicateType.Tags)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					List<String> tags = entity.getTags();
					for (int i = 0; i < tags.size(); i++)
					{
						if (tags.get(i).contains(value))
							return true;
					}
					return false;
				}
			};
			else if (type == PredicateType.Comment)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					List<CommentEntity> comments = entity.getComments();
					for (int i = 0; i < comments.size(); i++)
					{
						if (comments.get(i).getComment().contains(value))
							return true;
					}
					return false;
				}
			};
			else if (type == PredicateType.Friend)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					HashMap<Long, FriendEntity> friends = ApplicationData.getFriends();
					if (friends.containsKey(entity.getUid()))
					{
						FriendEntity friend = friends.get(entity.getUid());
						if (friend.getUsername().contains(value))
							return true;
					}
					return false;
				}
			};
			else
				throw new IllegalArgumentException("Unsupported Predicate Type: "+type.toString());
		}
		else
		{
			if (type == PredicateType.Title)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					return entity.getTitle().toLowerCase().contains(value);
				}
			};
			else if (type == PredicateType.Description)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					return entity.getDescription().toLowerCase().contains(value);
				}
			};
			else if (type == PredicateType.Tags)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					List<String> tags = entity.getTags();
					for (int i = 0; i < tags.size(); i++)
					{
						if (tags.get(i).toLowerCase().contains(value))
							return true;
					}
					return false;
				}
			};
			else if (type == PredicateType.Comment)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					List<CommentEntity> comments = entity.getComments();
					for (int i = 0; i < comments.size(); i++)
					{
						if (comments.get(i).getComment().toLowerCase().contains(value))
							return true;
					}
					return false;
				}
			};
			else if (type == PredicateType.Friend)
				return new ObjectEntityPredicate(){
				public boolean eval(ObjectEntity entity, String value)
				{
					HashMap<Long, FriendEntity> friends = ApplicationData.getFriends();
					if (friends.containsKey(entity.getUid()))
					{
						FriendEntity friend = friends.get(entity.getUid());
						if (friend.getUsername().toLowerCase().contains(value))
							return true;
					}
					return false;
				}
			};
			else
				throw new IllegalArgumentException("Unsupported Predicate Type: "+type.toString());
		}
	}
	
}

